package cn.tedu.tmall.passport.dao.repository.impl;
import cn.tedu.tamll.common.consts.PassportCacheConsts;
import cn.tedu.tmall.passport.dao.repository.IUserCacheRepository;
import cn.tedu.tamll.common.pojo.po.PermissionPO;
import cn.tedu.tamll.common.pojo.po.UserCachePO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Repository
public class UserCacheRepository implements IUserCacheRepository,PassportCacheConsts {

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    /**
     * 保存的主方法
     * @param userCachePO
     */
    @Override
    public void save(UserCachePO userCachePO) {
        //思考 这个userCachePO 要存到redis 我们用什么样的数据类型
        //String   key  userId value 权限列表

        //Set      key  userId value 权限列表
        //Zset
        //Hash bigKey:userId hashKey:
        //用 string list set 都可以, 考虑要不要更新, 如果更新删掉,从新放一份新的,覆盖
        //hash bigkey user_id,hashkey
        //Map<userId,Map<permissions,"article/add">> ???

        //Map<userId,List<Object>>
        // list key user_id
        // value List<> rightPush enable index=0 ,
        // permission index = 1

        //List     key  userId value 用户状态,权限1,权限2  可以实现,但是代码相对复杂

//        // 1 map 共享
//        saveUserByHashShared(userCachePO);
//        UserCachePO userCachePOByHashShared = getUserCachePOByHashShared(userCachePO.getUserId());
//        log.debug("模拟验证时的逻辑,从hash共享缓存中通过用户id获取用户信息:{}",userCachePOByHashShared);

        // 2 map 独享
        saveUserByHashNoShared(userCachePO);
       // UserCachePO userCachePOByHashNoShared = getUserCachePOByHashNoShared(userCachePO.getUserId());
       // log.debug("模拟验证时的逻辑,从hash独享缓存中通过用户id获取用户信息:{}",userCachePOByHashNoShared);

//        //3 list
//        saveUserByList(userCachePO);
//        UserCachePO userCachePOByList = getUserCachePOByList(userCachePO.getUserId());
//        log.debug("模拟验证时的逻辑,从list缓存中通过用户id获取用户信息:{}",userCachePOByList);


    }



    //******************************1 通过hash独享方式***************************************

    /**
     * 通过hash独享方式保存
     * @param userCachePO
     */
    private void saveUserByHashNoShared(UserCachePO userCachePO){
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        String key = KEY_PREFIX_USER_STATE + userCachePO.getUserId();
        Map<String,Object> smallMap = new HashMap<>();
        smallMap.put("enable",userCachePO.getEnable());
        smallMap.put("auth",userCachePO.getPermissions());
        hashOperations.putAll(key,smallMap);
        redisTemplate.expire(key,10L, TimeUnit.MINUTES);
    }

    /**
     * 通过独享用户id获取用户信息
     * @param userId
     * @return
     */
    private UserCachePO getUserCachePOByHashNoShared(Long userId){
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        String key = KEY_PREFIX_USER_STATE + userId;

        Integer enable = (Integer) hashOperations.get(key, "enable");
        List<PermissionPO> auth =(List<PermissionPO>)hashOperations.get(key, "auth");

        List<Object> enable1 = hashOperations.multiGet(key, Arrays.asList("enable", auth));

        UserCachePO userCachePO = new UserCachePO();
        userCachePO.setEnable(enable);
        userCachePO.setPermissions(auth);
        return userCachePO;
    }

    //******************************通过hash独享方式***************************************





    //******************************通过hash共享方式***************************************


    /**
     * 通过hash共享方式保存   所有的用户共享一个大map, 里面的每个小map表示一个用户
     * @param userCachePO
     */
    private void saveUserByHashShared(UserCachePO userCachePO){

        //所有人共用一个大map,里面的每个小map表示一个用户
        Map<String,Map<String,Object>> map1 = new HashMap<>();

        Map<String,Object> smallMap1 = new HashMap<>();
        smallMap1.put("userInfo_1",userCachePO);

        Map<String,Object> smallMap2 = new HashMap<>();
        smallMap1.put("userInfo_2",userCachePO);

        map1.put("user_status",smallMap1);
        map1.put("user_status",smallMap2);


        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        String key = KEY_PREFIX_USER_STATE;
        hashOperations.put(key,userCachePO.getUserId(),userCachePO);

    }

    /**
     * 通过用户id获取用户信息，共享
     * @param userId
     * @return
     */
    private UserCachePO getUserCachePOByHashShared(Long userId){
        HashOperations<String, Long, Object> hashOperations = redisTemplate.opsForHash();
        String key = KEY_PREFIX_USER_STATE;
        Object o = hashOperations.get(key, userId);
        return (UserCachePO)o;
    }


    //******************************通过hash共享方式***************************************


    //******************************通过list方式***************************************


    /**
     * 用list方式来对用户信息进行保存
     * @param userCachePO
     */
    private void saveUserByList(UserCachePO userCachePO){
        ListOperations<String, Serializable> listOperations = redisTemplate.opsForList();
        //passport:user-state:1
        String key = "passport:user-state:" + userCachePO.getUserId();

        listOperations.rightPush(key,String.valueOf(userCachePO.getEnable()));
        List<PermissionPO> permissions = userCachePO.getPermissions();
        for (PermissionPO permission : permissions) {
            listOperations.rightPush(key,permission.getAuthority());
        }
        List<Object> user = new ArrayList<>();
        user.add(userCachePO.getEnable());
        user.add(userCachePO.getPermissions());

        Map<Long, List<Object>> users = new HashMap<>();
        users.put(userCachePO.getUserId(),user);

    }

    /**
     * 通过list方式 获取用户信息
     * @param userId
     * @return
     */
    private UserCachePO getUserCachePOByList(Long userId){
        String key = "passport:user-state:" + userId;
        ListOperations<String, Serializable> listOperations = redisTemplate.opsForList();
        //弹出不行
        //listOperations.rightPop()
        //randomMembers set
        //index 通过一个key和list的下标获取下标对应的值
        //1 先获取到list的长度
        Long size = listOperations.size(key);
        //[0,"add","list","detail","create"]
        List<String> permissions = new ArrayList<>();
        //for (int i = 1; i<size; i++) {
        //    String index = listOperations.index(key, i);
        //    permissions.add(index);
        //}

        List<Serializable> range = listOperations.range(key, 0, -1);
        List<Serializable> otherPermissions = range.subList(1, range.size());

        UserCachePO userCachePO = new UserCachePO();
        userCachePO.setUserId(userId);
        //userCachePO.setEnable(Integer.valueOf(range.get(0)));//new Integer(range.get(0))
        //userCachePO.setPermissions(str2PermissionPO(otherPermissions));  //permissions
        return userCachePO;
    }

    private List<PermissionPO> str2PermissionPO(List<String> permissions){
        List<PermissionPO> result = new ArrayList<>();
        for (String permission : permissions) {
            PermissionPO permissionPO = new PermissionPO();
            permissionPO.setAuthority(permission);
            result.add(permissionPO);
        }
        return result;
    }

    //******************************通过list方式***************************************

}